import axios from 'axios';
import crypto from 'crypto';
import { WxConfig, WxLoginResponse, WxPhoneInfo } from './types';

export class WxLoginSDK {
  private config: WxConfig;
  private baseUrl = 'https://api.weixin.qq.com/sns';

  constructor(config: WxConfig) {
    this.config = config;
  }

  /**
   * 登录凭证校验
   * @param code 小程序登录时获取的 code
   */
  async code2Session(code: string): Promise<WxLoginResponse> {
    const url = `${this.baseUrl}/jscode2session`;
    const params = {
      appid: this.config.appId,
      secret: this.config.appSecret,
      js_code: code,
      grant_type: 'authorization_code'
    };

    try {
      const { data } = await axios.get(url, { params });
      if (data.errcode) {
        throw new Error(data.errmsg);
      }
      return data;
    } catch (error: any) {
      throw new Error(`微信登录凭证校验失败: ${error.message}`);
    }
  }

  /**
   * 解密手机号信息
   * @param sessionKey 会话密钥
   * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
   * @param iv 加密算法的初始向量
   */
  decryptPhoneNumber(
    sessionKey: string,
    encryptedData: string,
    iv: string
  ): WxPhoneInfo {
    try {
      // 解密
      const decipher = crypto.createDecipheriv(
        'aes-128-cbc',
        Buffer.from(sessionKey, 'base64'),
        Buffer.from(iv, 'base64')
      );
      
      let decoded = decipher.update(
        encryptedData,
        'base64',
        'utf8'
      );
      decoded += decipher.final('utf8');
      
      const phoneInfo: WxPhoneInfo = JSON.parse(decoded);
      
      // 校验水印
      if (phoneInfo.watermark.appid !== this.config.appId) {
        throw new Error('数据水印验证失败');
      }
      
      return phoneInfo;
    } catch (error: any) {
      throw new Error(`手机号解密失败: ${error.message}`);
    }
  }

  /**
   * 校验签名
   * @param signature 签名
   * @param rawData 原始数据
   * @param sessionKey 会话密钥
   */
  checkSignature(
    signature: string,
    rawData: string,
    sessionKey: string
  ): boolean {
    try {
      const sha1 = crypto
        .createHash('sha1')
        .update(rawData + sessionKey)
        .digest('hex');
      return signature === sha1;
    } catch (error) {
      return false;
    }
  }
} 